package com.dz.lm.web.task;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

import javax.annotation.Resource;

import com.dz.lm.common.exception.ServiceException;
import com.dz.lm.dao.agentreview.read.AgentReviewDao;
import com.dz.lm.dao.userorder.read.UserOrderDao;
import com.dz.lm.domain.agentreview.AgentReview;
import com.dz.lm.domain.agentreview.AgentReviewExample;
import com.dz.lm.domain.userorder.UserOrder;
import com.dz.lm.domain.userorder.UserOrderExample;
import com.dz.lm.domain.usersend.UserSend;
import com.dz.lm.domain.usersend.UserSendExample;
import com.dz.lm.service.userorder.UserOrderService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.dz.lm.common.constant.LmConstant;
import com.dz.lm.common.exception.DaoException;
import com.dz.lm.common.util.DzCache;
import com.dz.lm.common.utils.DateUtil;
import com.dz.lm.dao.account.write.AccountDao;
import com.dz.lm.dao.order.read.ProductOrderDao;
import com.dz.lm.dao.product.write.ProductDao;
import com.dz.lm.domain.order.Order;
import org.springframework.beans.factory.annotation.Autowired;

public class TaskExecutor {
	public Logger logger = LogManager.getLogger(TaskExecutor.class);
    
    @Resource(name = "writeProductDao")
    private ProductDao productDaoWrite;
    
    @Resource(name = "readProductOrderDao")
    private ProductOrderDao readProductOrderDao;
    
    @Resource(name = "readAccountDao")
    private com.dz.lm.dao.account.read.AccountDao readAccountDao;
    
    @Resource(name = "readAgentProductDao")
    private com.dz.lm.dao.product.read.AgentProductDao readAgentProductDao;
    
    @Resource(name = "writeAccountDao")
    private AccountDao writeAccountDao;
    
    @Resource(name = "writeProductOrderDao")
    private com.dz.lm.dao.order.write.ProductOrderDao writeProductOrderDao;
    
    @Resource(name = "writeOrderDao")
    private com.dz.lm.dao.order.write.OrderDao writeOrderDao;

	@Resource(name = "readUserSendDao")
	private com.dz.lm.dao.usersend.read.UserSendDao readUserSendDao;
	@Resource(name = "readAgentReviewDao")
	private AgentReviewDao readAgentReivewDao;

	@Resource(name ="writeAgentReviewDao")
	private com.dz.lm.dao.agentreview.write.AgentReviewDao writeAgentReviewDao;

	@Resource(name = "readUserOrderDao")
	private UserOrderDao readUserOrderDao;
	@Autowired
	private UserOrderService userOrderService;
	@Resource(name = "writeUserOrderDao")
	private com.dz.lm.dao.userorder.write.UserOrderDao writeUserOrderDao;
	/**
	 * 邀请代理超过24小时，返回账户
	 */
	public void agentAccountReturn(){
		logger.info("自动退反代理费任务已开始执行");

		try {
			UserSendExample ex = new UserSendExample();
			UserSendExample.Criteria cr = ex.createCriteria();
			cr.andStatusEqualTo(0);//发送状态
			Date now = com.smartlbs.util.DateUtil.getNowDateTime();
			Calendar instance = Calendar.getInstance();
			instance.setTime(now);
			instance.add(Calendar.HOUR_OF_DAY,-24);//24小时过期判断
			Date time = instance.getTime();
			cr.andCreateTimeLessThan(DateUtil.dateToString(time));
			List<UserSend> sends = readUserSendDao.selectByExample(ex);
			if(sends != null && sends.size() > 0){
				for (UserSend send : sends) {
					if(send.getFee() > 0){
						Double fee = send.getFee();//小费
						Map userInfo = new HashMap();
						//邀请人
						userInfo.put("userId", send.getUserId());
						Map<String, Object> Uaccount = readAccountDao.qryAccountInfoByUserId(userInfo);
						userInfo.clear();
						//邀请人账户
						userInfo.put("userId", send.getUserId());
						Map<String, Object> Saccount = readAccountDao.qryAccountInfoByUserId(userInfo);

						//计算代理人的账户金额
						BigDecimal agentCostB = new BigDecimal(fee);//消费
						BigDecimal amount = new BigDecimal(Uaccount.get("amount").toString());
						BigDecimal nowAmount = amount.add(agentCostB);
						BigDecimal cashAmount = new BigDecimal(Uaccount.get("cashAmount").toString());
						BigDecimal nowCashAmount = cashAmount.add(agentCostB);
						//代理人账户流水
						Order order = new Order();
						String orderId = getOrderId();
						order.setOrderId(orderId);
						order.setUserId(Integer.parseInt(Uaccount.get("userId").toString()));
						order.setAccountId(Integer.valueOf(Uaccount.get("accountId").toString()));
						order.setAmount(fee);
						order.setGatherAccountId(Integer.valueOf(Saccount.get("accountId").toString()));
						order.setGatherUserId(Integer.parseInt(Saccount.get("userId").toString()));
						order.setOrderType("8");//代理费 退回
						order.setPayType("3");//账户
						order.setState("13");//冲入
						writeOrderDao.addOrder(order);
						Uaccount.put("amount", nowAmount);
						Uaccount.put("cash_amount", nowCashAmount);
						writeAccountDao.updateAccount(Uaccount);
					}

				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		logger.info("自动退反代理费任务执行完毕");

	}

	/**
	 * 判断订单15天状态
	 */
	public void autoOrderDo()throws ServiceException{
		logger.info("15天的订单判断开始了");
		UserOrderExample ex = new UserOrderExample();
		UserOrderExample.Criteria cr = ex.createCriteria();
		Date date = new Date();
		Calendar instance = Calendar.getInstance();
		instance.setTime(date);
		instance.add(Calendar.DAY_OF_YEAR,-15);
		Date time = instance.getTime();
		List<Integer> set = new ArrayList();
		set.add(0);
		set.add(2);
		set.add(4);
		set.add(6);
		cr.andUpdateTimeGreaterThanOrEqualTo(DateUtil.getTimeStr(time));
		cr.andStatusIn(set);
		List<UserOrder> userOrders = readUserOrderDao.selectByExample(ex);
			if(userOrders != null && userOrders.size() > 0){
				userOrders.forEach(order -> {
					switch (order.getStatus()){
						case 0:
							try {
								userOrderService.update(order.getOrderId(),order.getApplyId(),1,"","",order.getBusinessId());
							} catch (Exception e) {
								e.printStackTrace();
							}
							break;
						case 2:
							try {
								userOrderService.update(order.getOrderId(),order.getApplyId(),3,"","",order.getBusinessId());
							} catch (Exception e) {
								e.printStackTrace();
							}

							break;
						case 4:
							try {
								userOrderService.update(order.getOrderId(),order.getApplyId(),3,"","",order.getBusinessId());
							} catch (Exception e) {
								e.printStackTrace();
							}

							break;
						case 6:
							try {
								userOrderService.update(order.getOrderId(),order.getApplyId(),3,"","",order.getBusinessId());
							} catch (Exception e) {
								e.printStackTrace();
							}
							break;
					}
				});
			}
	}
	/**
	 * 自动审核代理申请，超过2个月，审核未通过
	 */
	public void autoReivewAgent(){
		logger.info("自动审核代理申请任务已开始执行");
		try {
		AgentReviewExample ex = new AgentReviewExample();
		AgentReviewExample.Criteria cr = ex.createCriteria();
		cr.andStatusEqualTo(0);
		Date now = com.smartlbs.util.DateUtil.getNowDateTime();
		Calendar instance = Calendar.getInstance();
		instance.setTime(now);
		instance.add(Calendar.MONTH,-24);//24小时过期判断
		Date time = instance.getTime();
		cr.andCreateTimeLessThan(com.smartlbs.util.DateUtil.getDate2String(time,2));
			List<AgentReview> list = readAgentReivewDao.selectByExample(ex);
			if(list != null && list.size() > 0){
				for (AgentReview review : list) {
					review.setStatus(-1);
					review.setUpdateTime(com.smartlbs.util.DateUtil.getNowDateTimeString());
					writeAgentReviewDao.updateByPrimaryKeySelective(review);
				}
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}

		logger.info("自动审核代理申请任务执行完毕");

	}

	//自动分回扣
	public void divideRebate() {
		logger.info("自动分回扣任务已开始执行");
		try {
			Map<String, Object> param = new HashMap<String, Object>(); 
			//查询需要拆分返点的数据
			List<Map<String, Object>> divideRebateList= readProductOrderDao.qryDivideRebateList();
			Object busPayType = "";
			String amount = "";
			Object agentProductId = "";
			Object agentId = "";
			Object agentClass = "";
			Object upAgentId = "";
			BigDecimal amount1 = null;
			BigDecimal amount2 = null;
			Map<String, Object> upAgentInfo = null;
			for (Map<String, Object> rebate : divideRebateList) {
				busPayType = rebate.get("busPayType");
				amount = (rebate.get("amount") != null && !"".equals(rebate.get("amount"))) ? rebate.get("amount").toString() : "0";
				agentProductId = rebate.get("agentProductId");
				agentId = rebate.get("agentId");
				agentClass = rebate.get("agentClass");
				if ("1".equals(agentClass)) {//一级代理
					//增加一条入账订单记录
					String orderId = addOrder(agentId, amount, busPayType);
					//增加一条账户资金变动记录
					addAccoutSeq(orderId, agentId, amount);
					//更新账户资金
					subDivideRebate(agentId, amount, rebate);
					//更新原始待拆分数据标记为已处理
					param.put("orderId", rebate.get("orderId"));
					param.put("divideFlag","1");//标记为已处理
					writeProductOrderDao.updateProductOrder(param);
				} else if ("2".equals(agentClass)) {//二级代理
					//查找一级代理人
					param.put("productId", agentProductId);
					upAgentInfo = readAgentProductDao.qryUpAgentInfo(param);
					upAgentId = upAgentInfo.get("agentId");
					//拆分金额计算
					BigDecimal bigAmount = new BigDecimal(amount);
					BigDecimal bigRate = new BigDecimal(0.8);//80%
					amount1 = bigAmount.multiply(bigRate).setScale(2, BigDecimal.ROUND_HALF_UP);
					amount2 = bigAmount.subtract(amount1).setScale(2, BigDecimal.ROUND_HALF_UP);
					//增加2条入账订单记录（2条记录是1条一级代理，1条二级代理）
					String orderId1 = addOrder(agentId, amount1.toString(), busPayType);
					String orderId2 = addOrder(upAgentId, amount2.toString(), busPayType);
					//增加2条账户资金变动记录（2条记录是1条一级代理，1条二级代理）
					addAccoutSeq(orderId1, agentId, amount1.toString());
					addAccoutSeq(orderId2, upAgentId, amount2.toString());
					//更新2个账户资金（2条记录是1条一级代理，1条二级代理）
					subDivideRebate(agentId, amount1.toString(), rebate);//二级代理
					subDivideRebate(upAgentId, amount2.toString(), rebate);//一级代理
					//更新原始待拆分数据标记为已处理
					param.put("orderId", rebate.get("orderId"));
					param.put("divideFlag","1");//标记为已处理
					writeProductOrderDao.updateProductOrder(param);
				}
			}
		} catch (DaoException e) {
			e.printStackTrace();
		}
		logger.info("自动分回扣任务执行完毕");
	}

	private String addOrder(Object agentId, String amount, Object busPayType) {
		Order order = new Order();
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("userId", agentId);
		try {
			Map<String, Object> account = readAccountDao.qryAccountInfoByUserId(param);
			order.setGatherUserId(Integer.valueOf(agentId.toString()));
			String orderId = getOrderId();
			order.setOrderId(orderId);
			order.setGatherAccountId(Integer.valueOf(account.get("accountId").toString()));
			order.setAmount(Double.valueOf(amount.toString()));
			if ("4".equals(busPayType)) {
				order.setBody(LmConstant.LM_PAY_BODY_REBATE);
			} else if ("5".equals(busPayType)){
				order.setBody(LmConstant.LM_PAY_BODY_TURNOVER);
			}
			order.setOrderType("4");
			order.setPayType("1");
			order.setState("43");
			writeOrderDao.addOrder(order);
			return orderId;
		} catch (DaoException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private void addAccoutSeq(String orderId, Object agentId, String amount) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("userId", agentId);
		try {
			Map<String, Object> account = readAccountDao.qryAccountInfoByUserId(param);
			param.putAll(account);
			param.put("seqFlag", "1");//账户变动方向（1 来帐，2 往帐）
			param.put("changeType", "4");//交易类型（1 充值  2 支付 3 提现 4 返点）
			param.put("preAmount", param.get("amount"));
			BigDecimal addAmount = new BigDecimal(amount);
			BigDecimal accAmount = new BigDecimal(account.get("amount").toString());
			BigDecimal accCashAmount = new BigDecimal(account.get("cashAmount").toString());
			accAmount = accAmount.add(addAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
			accCashAmount = accCashAmount.add(addAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
			param.put("amount", accAmount.doubleValue());
			param.put("cash_amount", accCashAmount.doubleValue());
			param.put("orderId", orderId);
			writeAccountDao.addAccountSeq(param);
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}

	private void subDivideRebate(Object agentId, String amount, Map<String, Object> rebate) {
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("userId", agentId);
		try {
			Map<String, Object> account = readAccountDao.qryAccountInfoByUserId(param);
			BigDecimal addAmount = new BigDecimal(amount);
			BigDecimal accAmount = new BigDecimal(account.get("amount").toString());
			BigDecimal accCashAmount = new BigDecimal(account.get("cashAmount").toString());
			accAmount = accAmount.add(addAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
			accCashAmount = accCashAmount.add(addAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
			param.put("amount", accAmount.doubleValue());
			param.put("cash_amount", accCashAmount.doubleValue());
			writeAccountDao.updateAccount(param);
		} catch (DaoException e) {
			e.printStackTrace();
		}
	}
	
    private String getOrderId(){
    	String orderId = "";
    	@SuppressWarnings("unchecked")
		List<String> orderIdList = (List<String>) DzCache.getCacheCode("orderId");
    	if (orderIdList != null && orderIdList.get(0) != null) {
    		orderId = orderIdList.get(0);
    		orderIdList.remove(0);
		} else {
			long todayMaxorderId = DzCache.getCacheCode("todayMaxorderId") == null ? 0l :(long) DzCache.getCacheCode("todayMaxorderId");
			long maxId = todayMaxorderId + 100;
			DzCache.setCacheCode("todayMaxorderId", maxId);
			orderIdList = new ArrayList<String>();
			String strTime = DateUtil.getTimeStrFormat(new Date());
			String suffix = "00000000";
			for (long i = todayMaxorderId + 1; i < maxId + 1; i++) {
				suffix = suffix + "" + i;
				suffix = suffix.substring(suffix.length()- 8, suffix.length());
				orderIdList.add(strTime + "" + suffix);
			}
			orderId = orderIdList.get(0);
    		orderIdList.remove(0);
			DzCache.setCacheCode("orderId", orderIdList);
		}
		return orderId;
    }
}
